<template>
    <div>
        <button type="button" class="btn btn-white btn-success btn-round"
                v-on:click="selectFile()">
            <i class="ace-icon fa fa-upload blue"></i>
            {{text}}
        </button>
        <input ref="file" class="hidden" v-bind:id="inputId+'-input'" type="file" name="file"
               v-on:change="uploadFile()">

    </div>
</template>

<script>
    export default {
        name: 'big-file',
        props: {
            use: {
                default: null
            },
            inputId: {
                default: "file-upload"
            },
            suffixs: {
                default: []
            },
            text: {
                default: "上传大文件"
            },
            shardSize:{
                default: 50 * 1024
            },
            url:{
                default: "oss-append"
            },
            afterUpload: {
                type: Function,
                default: null
            }
        },
        data: function () {
            return {}
        },
        watch: {},
        methods: {
            /*选择图片*/
            selectFile() {
                let _this = this;
                $("#" + _this.inputId + "-input").trigger('click');
            },
            /*递归上传文件分片*/
            upload: function (param) {
                let _this = this;
                let shardIndex = param.shardIndex;
                let shardTotal = param.shardTotal;
                let shardSize = param.shardSize;
                let fileShard = _this.getFileShard(shardIndex, shardSize);
                //上传数据
                let fileReader = new FileReader();
                Progress.show(parseInt((shardIndex - 1) * 100 / shardTotal));
                fileReader.onload = function (e) {
                    let base64 = e.target.result;
                    param.shard = base64;
                    _this.$ajax.post(process.env.VUE_APP_SERVER + '/file/admin/' + _this.url, param).then((response) => {
                        Progress.show(parseInt(shardIndex * 100 / shardTotal));
                        if (shardIndex < shardTotal) {
                            //上传下一个分片
                            param.shardIndex = shardIndex + 1;
                            _this.upload(param);
                        } else {
                            Progress.hide();
                            _this.afterUpload(response.data);
                            $("#" + _this.inputId + "-input").val('');
                        }
                    });
                };
                fileReader.readAsDataURL(fileShard);
            },
            /*获取文件分片*/
            getFileShard: function (shardIndex, shardSize) {
                let _this = this;
                let file = _this.$refs.file.files[0];
                //当前分片起始位置
                let start = (shardIndex - 1) * shardSize;
                //当前分片结束位置
                let end = Math.min(file.size, start + shardSize);
                //从文件中截取当前分片的数据
                let fileShard = file.slice(start, end);
                return fileShard;
            },
            /*上传文件*/
            uploadFile() {
                let _this = this;
                let file = _this.$refs.file.files[0];
                //判断文件格式
                let suffixs = _this.suffixs;
                let fileName = file.name;
                let suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase();
                let validateSuffix = false;
                for (let i = 0; i < suffixs.length; i++) {
                    if (suffixs[i].toLowerCase() == suffix) {
                        validateSuffix = true;
                        break;
                    }
                }
                if (!validateSuffix) {
                    Toast.warning("文件格式不正确!只支持格式: " + suffixs.join(","));
                    $("#" + _this.inputId + "-input").val('');
                    return;
                }
                //文件分片 20MB
                // let shardSize = 20 * 1024 * 1024;
                let shardSize = _this.shardSize;
                //分片索引
                let shardIndex = 1;
                //总分片数
                let shardTotal = Math.ceil(file.size / shardSize);
                //文件大小
                let size = file.size;
                //生成文件标识key
                let key = hex_md5(file.name + file.size + file.type);
                let key10 = parseInt(key, 16);
                //62进制: 26个小写字母+26个大写字母+10个阿拉伯数字
                let key62 = Tool._10to62(key10);
                let param = {
                    'shardIndex': shardIndex,
                    'shardSize': shardSize,
                    'shardTotal': shardTotal,
                    'use': _this.use,
                    'name': file.name,
                    'suffix': suffix,
                    'size': size,
                    'key': key62
                };
                _this.check(param);
            },

            /*检查文件状态，是否已经上传过 或者说上传到第几个分片*/
            check(param) {
                let _this = this;
                _this.$ajax.get(process.env.VUE_APP_SERVER + '/file/admin/file/check/' + param.key).then((response) => {
                    let resp = response.data;
                    if (resp.success) {
                        let fileDto = resp.data;
                        if (!fileDto) {
                            //第一次上传
                            param.shardIndex = 1;
                            _this.upload(param);
                        } else if (fileDto.shardIndex === fileDto.shardTotal) {
                            Toast.success("文件极速秒传成功");
                            _this.afterUpload(resp);
                            $("#" + _this.inputId + "-input").val('');
                        } else {
                            //接着下一个分片
                            param.shardIndex = fileDto.shardIndex;
                            _this.upload(param);
                        }
                    } else {
                        Toast.warning("文件上传失败");
                        $("#" + _this.inputId + "-input").val('');
                    }

                });
            }

        }
    }
</script>

